'use strict';

const path = require('path');
const fs = require('fs');
const RpcServer = require('../rpc/server');
const RpcRegistry = require('../rpc/registry');

/**
 * 服务初始化基类
 */
class BaseInit {
  /**
   * 构造函数
   * @param {string} serviceName 服务名称
   */
  constructor(serviceName) {
    this.serviceName = serviceName;
    this.serviceType = '';
    this.servicePort = 0;
    this.isGlobal = false;
    this.serviceConfig = {};
    this.serviceDefinition = {};
    this.serviceInstance = null;
    this.serviceInstances = new Map();
    this.breakPort = null;

    // 读取baseConfig.json判断是否为调试模式
    this.isDebug = this._loadIsDebugSetting();
    console.log(`[${this.serviceName}] 构造函数 isDebug=${this.isDebug}`);
  }

  /**
   * 从baseConfig.json加载isDebug配置
   * @returns {boolean} 是否为调试模式
   * @private
   */
  _loadIsDebugSetting() {
    try {
      const baseConfigPath = path.resolve(process.cwd(), 'config/baseConfig.json');
      if (fs.existsSync(baseConfigPath)) {
        const configContent = fs.readFileSync(baseConfigPath, 'utf8');
        const config = JSON.parse(configContent);
        return config.isDebug === true;
      }
    } catch (error) {
      console.error(`[${this.serviceName}] 加载baseConfig.json失败，默认为开发环境:`, error);
    }

    // 默认为true，保留原有行为
    return process.env.NODE_ENV !== 'production';
  }

  /**
   * 初始化服务
   */
  async init() {
    try {
      // 加载服务配置
      await this.loadConfig();

      // 初始化全局服务代理
      await this.initGlobalServices();

      // 创建服务实例
      await this.createService();

      // 自动注册服务方法和属性
      await this.registerServiceMethodsAndProperties();

      // 注册服务
      await this.registerService();

      console.info(`服务已启动，端口: ${this.servicePort}`);
    } catch (error) {
      console.error(`初始化失败:`, error);
      throw error;
    }
  }

  /**
   * 加载服务配置
   */
  async loadConfig() {
    try {
      // 加载服务器配置
      const serverConfigPath = path.resolve(process.cwd(), 'config/server.json');
      const serverConfigContent = fs.readFileSync(serverConfigPath, 'utf8');
      this.serverConfig = JSON.parse(serverConfigContent);

      // 找到对应的服务配置
      const serviceConfig = this.serverConfig.processes.find(p => p.name === this.serviceName);

      if (!serviceConfig) {
        throw new Error(`找不到服务 ${this.serviceName} 的配置信息`);
      }

      this.serviceType = serviceConfig.type;
      this.servicePort = process.env.SERVICE_PORT ? parseInt(process.env.SERVICE_PORT) : serviceConfig.port;
      this.isGlobal = serviceConfig.global === 1;
      this.serviceConfig = serviceConfig;

      // 只有在调试模式下才处理调试端口
      if (this.isDebug) {
        // 处理调试端口
        if (serviceConfig.breakPort && !process.env.BREAK_PORT) {
          this.breakPort = serviceConfig.breakPort;
          console.log(`[${this.serviceName}] 直接使用配置的调试端口: ${this.breakPort}`);
        } else if (process.env.BREAK_PORT) {
          this.breakPort = parseInt(process.env.BREAK_PORT);
          console.log(`[${this.serviceName}] 使用环境变量设置的调试端口: ${this.breakPort}`);

          // 如果有调试端口，在启动时输出相关信息，便于确认调试是否生效
          process._debugProcess(process.pid);
          console.log(`[${this.serviceName}] 已激活调试模式，PID: ${process.pid}, 调试端口: ${this.breakPort}`);
        }
      } else {
        console.log(`[${this.serviceName}] 生产环境模式，不启用调试端口`);
      }

      // 加载service.json配置
      const servicePath = path.resolve(process.cwd(), `src/${this.serviceType}/service.json`);
      if (!fs.existsSync(servicePath)) {
        throw new Error(`找不到服务定义文件: ${servicePath}`);
      }

      const serviceContent = fs.readFileSync(servicePath, 'utf8');
      const serviceJson = JSON.parse(serviceContent);

      // 存储所有服务定义
      this.serviceDefinitions = new Map();

      // 遍历service.json中的所有服务定义
      for (const [serviceName, definition] of Object.entries(serviceJson)) {
        this.serviceDefinitions.set(serviceName, {
          methods: definition.methods || [],
          properties: definition.properties || []
        });
      }

      console.info(`配置加载完成，已加载 ${this.serviceDefinitions.size} 个服务定义`);
    } catch (error) {
      console.error(`加载配置失败:`, error);
      throw error;
    }
  }

  /**
   * 初始化全局服务代理
   */
  async initGlobalServices() {
    try {
      // 确保 global.services 对象存在
      if (!global.services) {
        global.services = {};
      }

      console.debug(`初始化全局服务代理...`);

      // 检索所有全局服务
      const globalServices = this.serverConfig.processes.filter(p => p.global === 1 && p.name !== this.serviceName);

      for (const serviceConfig of globalServices) {
        // 如果服务尚未初始化为全局代理
        if (!global[serviceConfig.name] && !global.services[serviceConfig.name]) {
          console.debug(`创建全局服务代理: ${serviceConfig.name}`);

          // 创建服务代理
          const proxy = this.createServiceProxy(serviceConfig.name, serviceConfig.port, serviceConfig.host);

          // 注册到全局对象
          global[serviceConfig.name] = proxy;
          global.services[serviceConfig.name] = proxy;
        }
      }

      console.debug(`全局服务代理初始化完成`);

      // 初始化非全局服务代理
      await this.initNonGlobalServices();

    } catch (error) {
      console.error(`初始化全局服务代理失败:`, error);
      throw error;
    }
  }

  /**
   * 初始化非全局服务代理
   */
  async initNonGlobalServices() {
    try {
      console.debug(`初始化非全局服务代理...`);

      // 检查是否需要初始化RPC代理
      let shouldInitRpcProxy = false;

      // 检查是否有非全局服务
      const nonGlobalServices = this.serverConfig.processes.filter(p => p.global !== 1);
      if (nonGlobalServices.length > 0) {
        shouldInitRpcProxy = true;
      }

      if (shouldInitRpcProxy) {
        console.debug(`存在非全局服务，初始化RPC代理...`);

        // 初始化RPC代理 - 移除自动连接选项
        await RpcRegistry.initializeRpcProxy({
          configDir: path.resolve(process.cwd(), 'config'),
          autoConnect: false // 修改为false，不再自动连接
        });

        console.debug(`RPC代理初始化完成，现在可以通过 RPC.serviceName[port].method() 访问非全局服务`);
      } else {
        console.debug(`没有非全局服务，跳过RPC代理初始化`);
      }

    } catch (error) {
      console.error(`初始化非全局服务代理失败:`, error);
      // 不抛出错误，以免阻止全局服务的初始化
      console.warn(`将继续初始化其他服务`);
    }
  }

  /**
   * 创建服务代理
   * @param {string} serviceName 服务名称
   * @param {number} port 端口号
   * @param {string} host 主机地址
   * @returns {object} 服务代理
   */
  createServiceProxy(serviceName, port, host) {
    const RpcRegistry = require('../rpc/registry');
    const proxy = RpcRegistry.getService(serviceName, port, host);
    return proxy;
  }

  /**
   * 创建服务实例（子类实现）
   */
  async createService() {
    throw new Error('子类必须实现createService方法');
  }
  /**
   * 创建服务实例（子类实现）
   */
  async createOneService(name, instance) {
    const service = new instance();
    this.addServiceInstance(name, service);
    await service.init();
    console.log(`[${name}] 服务实例已创建`);
  }

  /**
   * 注册服务方法和属性
   */
  async registerServiceMethodsAndProperties() {
    try {
      console.log(`[${this.serviceName}] 注册服务方法和属性...`);

      // 遍历所有服务实例
      for (const [instanceName, instance] of this.serviceInstances.entries()) {
        console.log(`[${this.serviceName}] 处理实例: ${instanceName}`);

        // 获取该实例的服务定义
        const serviceDefinition = this.serviceDefinitions.get(instanceName);
        if (!serviceDefinition) {
          console.warn(`[${this.serviceName}] 找不到服务 ${instanceName} 的定义，跳过注册`);
          continue;
        }

        // 注册方法
        for (const methodInfo of serviceDefinition.methods) {
          const methodName = methodInfo.name;

          if (typeof instance[methodName] === 'function') {
            console.log(`[${this.serviceName}] 注册方法: ${instanceName}.${methodName}`);
            instance[methodName] = instance[methodName].bind(instance);

            // 构建方法选项
            const methodOptions = {
              needReturn: !!methodInfo.returns,
              returnType: methodInfo.returns,
              parameters: methodInfo.parameters || []
            };

            this.registerServiceMethod(instance, methodName, instance[methodName], methodOptions);
          } else {
            console.warn(`[${this.serviceName}] 方法不存在: ${instanceName}.${methodName}`);
          }
        }

        // 注册属性
        for (const propInfo of serviceDefinition.properties) {
          const propertyName = typeof propInfo === 'object' ? propInfo.name : propInfo;

          if (propertyName && propertyName in instance) {
            console.log(`[${this.serviceName}] 注册属性: ${instanceName}.${propertyName}`);

            // 获取属性描述符
            const descriptor = Object.getOwnPropertyDescriptor(
              Object.getPrototypeOf(instance),
              propertyName
            );

            // 如果是getter/setter属性
            if (descriptor && (descriptor.get || descriptor.set)) {
              this.registerServiceProperty(
                instance,
                propertyName,
                descriptor.get,
                descriptor.set
              );
            } else {
              this.registerServiceProperty(
                instance,
                propertyName,
                () => instance[propertyName],
                (value) => { instance[propertyName] = value; }
              );
            }
          } else if (propertyName) {
            console.warn(`[${this.serviceName}] 属性不存在: ${instanceName}.${propertyName}`);
          }
        }
      }

      console.log(`[${this.serviceName}] 服务方法和属性注册完成`);
    } catch (error) {
      console.error(`[${this.serviceName}] 注册服务方法和属性失败:`, error);
      throw error;
    }
  }

  /**
   * 注册服务方法
   * @param {object} serviceInstance 服务实例
   * @param {string} methodName 方法名称
   * @param {Function} method 方法实现
   * @param {object} options 方法选项 (needReturn, returnType)
   */
  registerServiceMethod(serviceInstance, methodName, method, options = {}) {
    if (typeof serviceInstance.registerMethod === 'function') {
      // 标准化 returnType 格式
      if (options.returnType) {
        // 如果 returnType 是数组，确保它的格式正确
        if (Array.isArray(options.returnType)) {
          // 不需要更改
        } else if (typeof options.returnType === 'string') {
          // 如果是字符串，转换为数组
          options.returnType = [options.returnType];
        } else {
          // 其他情况，保持原样
        }
      }

      // 传递方法选项到服务实例
      serviceInstance.registerMethod(methodName, method.bind(serviceInstance), options);

      const returnInfo = options.needReturn ?
        `返回类型: ${JSON.stringify(options.returnType)}` : '无返回值';
      console.log(`[${this.serviceName}] 注册方法: ${serviceInstance.name}.${methodName} (${returnInfo})`);
    } else {
      console.warn(`[${this.serviceName}] 服务 ${serviceInstance.name} 不支持注册方法`);
    }
  }

  /**
   * 注册服务属性
   * @param {object} serviceInstance 服务实例
   * @param {string} propertyName 属性名称
   * @param {Function|any} getter 获取属性的函数或值
   * @param {Function} setter 设置属性的函数（可选）
   */
  registerServiceProperty(serviceInstance, propertyName, getter, setter = null) {
    if (typeof serviceInstance.registerProperty === 'function') {
      serviceInstance.registerProperty(propertyName, getter, setter);
      console.log(`[${this.serviceName}] 注册属性: ${serviceInstance.name}.${propertyName}`);
    } else {
      console.warn(`[${this.serviceName}] 服务 ${serviceInstance.name} 不支持注册属性`);
    }
  }

  /**
   * 添加服务实例
   * @param {string} serviceName 服务名称
   * @param {object} serviceInstance 服务实例
   */
  addServiceInstance(serviceName, serviceInstance) {
    this.serviceInstances.set(serviceName, serviceInstance);
    // global[serviceName] = serviceInstance;

    // 如果是主要服务实例，也设置到 serviceInstance 属性
    if (!this.serviceInstance || serviceName === this.serviceName) {
      this.serviceInstance = serviceInstance;
    }
  }

  /**
   * 注册服务
   */
  async registerService() {
    try {
      console.log(`[${this.serviceName}] 注册RPC服务...`);

      // 创建RPC服务器
      this.rpcServer = new RpcServer(this.serviceName, this.servicePort, this.serviceConfig.host);

      // 注册服务实例
      const serviceInstances = Array.from(this.serviceInstances.entries());

      for (const [name, instance] of serviceInstances) {
        console.log(`[${this.serviceName}] 注册服务实例: ${name}`);
        // 仅为主服务设置 isGlobal
        const isMainService = (name === this.serviceName);
        this.rpcServer.registerService(name, instance, isMainService && this.isGlobal);
      }

      // 启动服务
      await this.rpcServer.start();

      // 注册全局服务
      if (this.isGlobal) {
        console.log(`[${this.serviceName}] 注册到全局服务...`);

        // 获取主服务实例
        const mainServiceName = Array.from(this.serviceInstances.keys())[0];
        const mainService = this.serviceInstances.get(mainServiceName);

        // 注册到全局对象
        global[this.serviceName] = mainService;

        // 确保 global.services 对象存在
        if (!global.services) {
          global.services = {};
        }

        // 添加到 global.services
        global.services[this.serviceName] = mainService;

        console.log(`[${this.serviceName}] 全局服务注册完成`);
      }

      console.log(`[${this.serviceName}] RPC服务注册完成, 端口: ${this.servicePort}`);

      // 注册进程退出处理
      process.on('SIGINT', this.handleExit.bind(this));
      process.on('SIGTERM', this.handleExit.bind(this));

    } catch (error) {
      console.error(`[${this.serviceName}] 注册服务失败:`, error);
      throw error;
    }
  }

  /**
   * 处理进程退出
   */
  async handleExit() {
    console.log(`[${this.serviceName}] 正在关闭服务...`);

    try {
      // 关闭RPC服务
      if (this.rpcServer) {
        console.log(`[${this.serviceName}] 关闭RPC服务...`);
        await this.rpcServer.stop();
      }

      // 关闭所有服务实例
      for (const [name, instance] of this.serviceInstances.entries()) {
        if (typeof instance.close === 'function') {
          console.log(`[${this.serviceName}] 关闭服务实例: ${name}`);
          await instance.close();
        }
      }

      console.log(`[${this.serviceName}] 服务已安全关闭`);
      process.exit(0);
    } catch (error) {
      console.error(`[${this.serviceName}] 关闭服务时发生错误:`, error);
      process.exit(1);
    }
  }
}

module.exports = BaseInit; 
